import time
from threading import Thread
# import threading
import numpy as np
import pandas as pd
import sqlite3
from tqsdk import TqApi, TqAuth, TqKq
from MyTT import EMA, SUM
from rich.console import Console
from rich.theme import Theme
from MyTT import REF, EMA

# 定义颜色主题
# 定义更明亮显眼的颜色主题
custom_theme = Theme({
    "info": "bright_cyan",
    "warning": "bright_yellow",
    "error": "bright_red",
    "success": "bright_green",
    "trade": "bold bright_magenta"
})
console = Console(theme=custom_theme)

# 定义全局变量
symbols = []
api=None
threads = []
# stop_event = threading.Event()
# api = TqApi(account=TqKq(), auth=TqAuth("cps168", "alibaba"))



def get_symbols():
    try:
        conn = sqlite3.connect('trade_monitor.db')
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM products WHERE is_monitored=1")
        products = cursor.fetchall()
        conn.close()
        symbols=[row[2] for row in products]
    except Exception as e:
        print(f"从数据库获取监控品种时出错: {e}", style="error")
    return symbols

def stop_loss(symbol):
        console.print(f"{time.strftime('%X')} 开始检查{symbol}止损条件", style="warning")
        klines = api.get_kline_serial(symbol, 60,data_length=300)
        quote = api.get_quote(symbol)
        position = api.get_position(symbol)

        console.print(f"{time.strftime('%X')} 开始处理 {symbol}", style="warning") 
        # api.wait_update(deadline=time.time() + 1)
        if True: # 条件一：api.is_changing(klines.iloc[-1], "datetime") 条件二：api.is_changing(klines.iloc[-1], "close") 条件三：api.is_changing(quote,["last_price", "bid_volume1", "ask_volume1"]) 
                console.print(f"{time.strftime('%X')} 数据更新", style="info")
                try:
                    close = klines.close
                    low = klines.low
                    open = klines.open
                    high = klines.high
                    # 转换为 numpy 数组，方便使用 MyTT 计算
                    close = np.array(close)
                    low = np.array(low)
                    open = np.array(open)
                    high = np.array(high)

                    Q = (3 * close + low + open + high) / 6
                    # 计算操盘线
                    trading_line = (26 * Q + 25 * REF(Q, 1) + 24 * REF(Q, 2) + 23 * REF(Q, 3) + 22 * REF(Q, 4) + 21 * REF(Q, 5) + 20 * REF(Q, 6) + 19 * REF(Q, 7) + 18 * REF(Q, 8) + 17 * REF(Q, 9) + 16 * REF(Q, 10) + 15 * REF(Q, 11) + 14 * REF(Q, 12) + 13 * REF(Q, 13) + 12 * REF(Q, 14) + 11 * REF(Q, 15) + 10 * REF(Q, 16) + 9 * REF(Q, 17) + 8 * REF(Q, 18) + 7 * REF(Q, 19) + 6 * REF(Q, 20) + 5 * REF(Q, 21) + 4 * REF(Q, 22) + 3 * REF(Q, 23) + 2 * REF(Q, 24) + REF(Q, 26)) / 351
                    # 计算空头线
                    short_line = EMA(trading_line, 7)
                    # 平仓条件判断
                    print("条件值是：",trading_line[-2],short_line[-2])
                    if len(trading_line) >= 2 and len(short_line) >= 2:
                        if position.pos_short > 0 and trading_line[-2] > short_line[-2]:
                            if symbol.startswith('SHFE'):
                                # 平今仓
                                if position.pos_short_today > 0:
                                    api.insert_order(
                                        symbol=symbol,
                                        direction="BUY",
                                        offset="CLOSETODAY",
                                        volume=position.pos_short_today
                                    )
                                    console.print(
                                        f"{time.strftime('%X')} 平SHFE{symbol}今空仓: 手数: {position.pos_short_today}",
                                        style="trade"
                                    )
                                # 平昨仓
                                if position.pos_short_his > 0:
                                    api.insert_order(
                                        symbol=symbol,
                                        direction="BUY",
                                        offset="CLOSEYESTERDAY",
                                        volume=position.pos_short_his
                                    )
                                    console.print(
                                        f"{time.strftime('%X')} 平SHFE{symbol}昨空仓: 手数: {position.pos_short_his}",
                                        style="trade"
                                    )
                            else:
                                api.insert_order(
                                    symbol=symbol,
                                    direction="BUY",
                                    offset="CLOSE",
                                    volume=position.pos_short
                                )
                                console.print(
                                    f"{time.strftime('%X')} 平{symbol}空仓: 手数: {position.pos_short}",
                                    style="trade"
                                )

                        if position.pos_long > 0 and trading_line[-2] < short_line[-2]:
                            if symbol.startswith('SHFE'):
                                # 平今仓
                                if position.pos_long_today > 0:
                                    api.insert_order(
                                        symbol=symbol,
                                        direction="SELL",
                                        offset="CLOSETODAY",
                                        volume=position.pos_long_today
                                    )
                                    console.print(
                                        f"{time.strftime('%X')} 平SHFE{symbol}今多仓: 手数: {position.pos_long_today}",
                                        style="trade"
                                    )
                                # 平昨仓
                                if position.pos_long_his > 0:
                                    api.insert_order(
                                        symbol=symbol,
                                        direction="SELL",
                                        offset="CLOSEYESTERDAY",
                                        volume=position.pos_long_his
                                    )
                                    console.print(
                                        f"{time.strftime('%X')} 平SHFE{symbol}昨多仓: 手数: {position.pos_long_his}",
                                        style="trade"
                                    )
                            else:
                                api.insert_order(
                                    symbol=symbol,
                                    direction="SELL",
                                    offset="CLOSE",
                                    volume=position.pos_long
                                )
                                console.print(
                                    f"{time.strftime('%X')} 平{symbol}多仓: 手数: {position.pos_long}",
                                    style="trade"
                                )
                except Exception as e:
                    console.print(f"处理 {symbol} 止损逻辑时出错: {e}", style="error")   

if __name__ == "__main__":
    try:
        api = TqApi(account=TqKq(), auth=TqAuth("cps168", "alibaba"))
        symbols = get_symbols()
        while True:
            deadline = time.time() + 1  # 设置超时时间为 10 秒
            api.wait_update(deadline=deadline)
            for symbol in symbols:
                #方案一：会有错误提示：不能在协程中调用 wait_update, 如需在协程中等待业务数据更新请使用 register_update_notify
                # thread_stp=threading.Thread(target=stop_loss,args=(symbol,),daemon=True).start()
                ## threads.append(thread_stp)
                # time.sleep(2)  

                #方案二：仍然有上述错误提示
                # threading.Thread(target=stop_loss,args=(symbol,),daemon=True).start()
                # time.sleep(2)

                #方案三：
                # Thread(target=stop_loss,args=(symbol,),daemon=True)
                stop_loss(symbol)
    except KeyboardInterrupt:
    #except Exception as e:
        #print(f"程序运行出错: {e}", style="error")
        pass
    finally:
        api.close()
        console.print("程序已停止", style="info")


